/******************************************************************************/
/* Files to Include                                                           */
/******************************************************************************/

/* Device header file */
#if defined(__dsPIC33E__)
	#include <p33Exxxx.h>
#elif defined(__dsPIC33F__)
	#include <p33Fxxxx.h>
#endif

#include <libq.h>
#include <stdbool.h>       /* Includes true/false definition                  */
#include <stdio.h>         /* Necesario para scanf*/
#include "system.h"        /* System funct/params, like osc/peripheral config */
#include "user.h"          /* User funct/params, such as InitApp              */
#include <libpic30.h>       /*Necesaria para el uso de retardos*/
#include "xlcd.h"
#include <adc.h>
#include "leds.h"
#include "switches.h"


/******************************************************************************/
/* Global Variable Declaration                                                */
/******************************************************************************/
#define Delay_TSAMP_min   (unsigned long)(2000ULL*(FCY)/1000000000ULL)/*2000 ns*/

#define EXTRABITS       3   /*Cambiar por extrabits)*/
#define CANTMUESTRAS     64  /*Cambiar por 4^extrabits */
#define FACTORESC    6   /*Cambiar por 2*extrabits */

#define CONSTAJUSTE    0.7f /*Constante para ajustar al recorrido físico del LDVT*/
/******************************************************************************/
/* Main Program                                                               */
/******************************************************************************/
static enum {ENVIANDO, NO_ENVIANDO} enviando_st; /*Define estado de envío por UART1*/
volatile register int result asm("A");

int main(void)
{
    
    enviando_st = NO_ENVIANDO;
    unsigned int k = 0;
    int ADCvalue = 0;
    double ADCvaluefloat;
    double ajustado;
    char str[30]; /*Cadena para almacenar valor convertido a texto y luego enviar al LCD*/

    /* Initialize IO ports and peripherals */

    InitApp();

    CORCONbits.SATA=0; /*Accumulator A saturation disabled.
                        * Esto permite usar los 40 bits del acumuladador A*/

    while(1)
    {

        result = __builtin_clr(); /*Limpiar el acumulador A*/

        /*Promedia 64 muestras antes mostrar*/
        for(k=0;k!=CANTMUESTRAS;k++)
        {

            __delay32(Delay_TSAMP_min); /*Retardo para asegurar tiempo de muestreo mínimo
                             * TSAMP_min = 3 * TAD */
            ConvertADC1(); /* Start the conversion*/
            while (BusyADC1()); /* Wait for the conversion to complete*/

            ADCvalue = ReadADC1(0);/*Esperado un decimal de -1 to 0.99996*/

            result = __builtin_add(result,ADCvalue,0);
       }
        /* Ver 4.12 ACCUMULATOR USAGE (dsPIC30F, dsPIC33F AND dsPIC33E DEVICES de
         * 16-bit MCU and DSC Programmer’s Reference Manual
         */

        result = __builtin_sftac(result,FACTORESC); 
        /*Desplazamiento de bits según factor de escala*/

        /*Lee el valor en el registro ACCAH del Acumulador y lo convierte en
         * el valor en punto flotante*/

         ADCvaluefloat = _itofQ15(__builtin_sac(result,0)); 
        
         /*TODO Falta mejorar constante de corrección*/
         ajustado = CONSTAJUSTE * ADCvaluefloat; /*Esperado un rango entre -0.5 y 0.5mm*/
    
          /*Convierte valor en una cadena de texto*/
         sprintf(str, "Val %+.4f mm", ajustado);

         while(BusyXLCD());
        SetDDRamAddr(0x80); /*Dirección de primera linea*/

        PutsXLCD(str);

        TogleLED(1);

        if (enviando_st == ENVIANDO){
             while(BusyXLCD());
             SetDDRamAddr(0xC0); /*Imprimir en la Segunda línea de LCD*/
             PutsXLCD("Enviando");
             /*Convertir a texto*/
             printf ( "%.9f\n",ajustado ); /*Enviar a stdout*/
        }

        if (!S1)
        {
            __delay_ms(300); /*Retardo para evitar el rebote de switch*/
            if(enviando_st == ENVIANDO)
            {
               enviando_st = NO_ENVIANDO; /*Cambio de estado*/
           
               /*Si es el fin de medición enviar un @ por puerto serie*/
               printf ( "@\n" ); /*Caracter indicado fin de transmisión*/
               /*Quitar mensaje "Enviando" del display*/
               while( BusyXLCD() );
               WriteCmdXLCD(CLEAR_XLCD);
            }
            else /*enviando_st == NO_ENVIANDO*/
            {
                enviando_st = ENVIANDO; /*Cambio de estado*/
            }
        }

    }

}
